package com.spzx.product.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spzx.product.api.domain.vo.CategoryVo;
import com.spzx.product.domain.Category;
import com.spzx.product.domain.vo.CategoryExcelVo;
import com.spzx.product.mapper.CategoryMapper;
import com.spzx.product.service.ICategoryService;
import com.spzx.product.util.CategoryHelper;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 商品分类Service业务层处理
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper,Category> implements ICategoryService {

    @Autowired
    private CategoryMapper categoryMapper;

    @Override
    public List<Category> treeSelect(Long parentId) {
        List<Category> categoryList = categoryMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getParentId, parentId));

        if(!CollectionUtils.isEmpty(categoryList)){
            categoryList.forEach(item -> {
                Long count = categoryMapper.selectCount(new LambdaQueryWrapper<Category>().eq(Category::getParentId, item.getId()));
                if(count>0){
                    item.setHasChildren(true);
                }else{
                    item.setHasChildren(false);
                }
            });
        }

        return categoryList;
    }



    @Override
    public List<Long> getAllParentId(Long id) {
        List<Long> idList = new ArrayList<>();

        //存放分类对象集合，分类级别顺序： [Category3,Category2,Category1]   ,需要 [1,2,3]
        List<Category> list =  this.getParentIdList(id,new ArrayList<Category>());
        int size = list.size();
        for (int i = size-1; i >=0 ; i--) {
            idList.add(list.get(i).getId());
        }

        return idList;
    }

    /**
     * 递归：
     *      1.同类问题
     *      2.必须结束条件
     *      3.StackOverflowError 避免死归
     * @param id 当前分类id
     * @param categoryList 自带数据容器，方法返回的数据放在这个容器里。
     * @return
     */
    private List<Category> getParentIdList(Long id,List<Category> categoryList) {
        while (id>0) {
            Category category = categoryMapper.selectById(id);
            categoryList.add(category);

            return getParentIdList(category.getParentId(), categoryList);
        }
        return categoryList;
    }

    /*    @Override
    public List<Long> getAllParentId(Long id) {
        List<Long> idList = new ArrayList<>();

        Category category3 = categoryMapper.selectById(id);
        Category category2 = categoryMapper.selectById(category3.getParentId());
        Category category1 = categoryMapper.selectById(category2.getParentId());

        idList.add(category1.getId());
        idList.add(category2.getId());
        idList.add(category3.getId());

        return idList;
    }*/


    @Override
    public void exportData(HttpServletResponse response) {
        try {
            //1.设置响应内容类型以及编码
            response.setContentType("application/vnd.ms-excel"); //表示内容是一个Excel文档类型。服务器告诉客户端，返回给客户端的是啥类型的数据
            response.setCharacterEncoding("utf-8");

            //2.设置下载（附件打开）并且设置跨域允许头信息
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("分类数据", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); //跨域请求时允许响应指定头信息

            //3.查询数据，转换类型
            List<Category> categoryList = categoryMapper.selectList(null);
            //2.类型转换  List<Category>   =>   List<CategoryExcelVo>
            List<CategoryExcelVo> categoryExcelVoList = new ArrayList<>();
            for (Category category : categoryList) {
                CategoryExcelVo categoryExcelVo = new CategoryExcelVo();
                BeanUtils.copyProperties(category,categoryExcelVo);
                categoryExcelVoList.add(categoryExcelVo);
            }

            //4.导出
            EasyExcel.write(response.getOutputStream(),CategoryExcelVo.class).sheet("分类数据").doWrite(categoryExcelVoList);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public void importData(MultipartFile file) {
        try {
            List<CategoryExcelVo> categoryExcelVoList =
                    EasyExcel.read(file.getInputStream())
                    .head(CategoryExcelVo.class)
                    .sheet()
                    .doReadSync();

            List<Category> categoryList = new ArrayList<>();
            for (CategoryExcelVo vo : categoryExcelVoList) {
                Category category = new Category();
                BeanUtils.copyProperties(vo,category);
                categoryList.add(category);
            }

            super.saveBatch(categoryList); //mybatis-plus 业务层父接口有批量保存方法。dao层没有批量方法。

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    @Override
    public List<CategoryVo> getOneCategory() {
        List<Category> categoryList = categoryMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getParentId, 0));

        return categoryList.stream().map(category->{
            CategoryVo vo = new CategoryVo();
            BeanUtils.copyProperties(category,vo);
            return vo;
        }).collect(Collectors.toList());
    }


    @Override
    public List<CategoryVo> tree() {
        // 1. 查询所有分类列表数据 703条   List<Category>
        List<Category> categoryList = categoryMapper.selectList(null);

        // 2.将  List<Category> 转换  List<CategoryVo> 类型集合
        List<CategoryVo> categoryVoList = categoryList.stream().map(category -> {
            CategoryVo vo = new CategoryVo();
            BeanUtils.copyProperties(category,vo);
            return vo;
        }).collect(Collectors.toList());

        // 3. 构建树结构
        return CategoryHelper.buildTree(categoryVoList);
    }
}